#include <stdio.h> 
#include <stdlib.h> //包含malloc函数 

#define BUFFERSIZE 25
//定义一本书 
struct book 
{
	char name[BUFFERSIZE];   //书名
	char author[BUFFERSIZE]; //作者 
	char press[BUFFERSIZE];  //出版社 
	int num;         //图书编号 
};

struct Node//节点
{
    struct book data; //数据域->一本书的信息 相当于操作了整个struct book单元的数据，即data.成员名 
	struct Node*next;    //指针域  指向下一个结点 
};

//typedef node struct Node*;

struct Node* headNode=NULL;//定义头结点 
void printMenu(); //打印用户界面  
void printlist();//输出链表
void readfile() ;//读取文件

void addNodeByTail();                            // 1.添加图书信息
struct Node* searchbynum();                      // 2.查找图书信息 
void deleteNode();                               // 3.按照num删除图书信息
void sortbyBubble() ;                           // 4.按照num排列图书信息



int main()
{
	
	int n; 
	
	//用户欢迎界面构建 
	while(1){
    	printMenu(); 
    	readfile(); 
    	printf("Enter Command (1 - 4) ");//读取用户输入数字选择对应功能
    	scanf("%d",&n);
		switch (n){
		   
			case 1:addNodeByTail();//添加图书信息
			     break;
			case 2:
			{
				 struct Node*p=searchbynum();//查找图书信息
					 if(p!=NULL){
			         	printf("Name：  %s\nAuthor:    %s\nPublisher: %s\n \
						 ID:        %d \n",p->data.name,p->data.author,p->data.press,p->data.num);
			        
					 }
					 else{
					 	printf("Failed to Find");
					 }
					system("pause");//暂停 
                    system("cls");//清屏
			        
			     break;
			}
			        
			case 3: deleteNode(); //删除图书信息
			     break;
			case 4:sortbyBubble();  //排列图书信息
			     break;	
			case 5:goto over;
			default:
				printf("Command Wrong Enter It Again： \n");
				break;
		} 
		puts("Loop One");
	}
	over:
		puts("Bye");
		return 0;

}
void printMenu() //菜单 
{
	
	printf("*********************************\n");
	printf("*Welcome to the simple SQL\t*\n");	
	printf("*********************************\n");
	printf("*\tMenu:\t\t*\n");
	printf("*********************************\n");
	printf("*\t1.Add a Book\t\t*\n");
	printf("*\t2.Find a Book\t\t*\n");
	printf("*\t3.Delete a Book\t\t*\n");
	printf("*\t4.Sort Books\t\t*\n");
	printf("*\t5.Exit the SQL\t\t*\n");
	printf("*********************************\n");

}




void printlist()//输出链表 
{
	struct Node* pMove=headNode->next;//打印时不打印headNode 从第二个开始打印 
	printf("book\tauthor\tpress\tnum\n");
	while(pMove){//pMove不是指向null则继续打印 
		printf("%s\t%s\t%s\t%d\n",pMove->data.name,pMove->data.author,pMove->data.press,pMove->data.num);
		pMove=pMove->next;//移动到下一位 	
		} 
	printf("\t"); 
} 

void readfile() 
{
	char *filepath = "D:\\testtxt\\a.txt";
	FILE *fp=fopen(filepath,"r");//打开文件 
	if(fp==NULL){
		printf("Failed to open:%s\n", filepath);
		return; 
	}
	//读文件
	// feof()函数用于判断是否是文件末尾
	//while(fp != NULL){
	//创建新结点 
   struct Node* newNode=(struct Node*)malloc(sizeof(struct Node));//创建新结点  用于建立链表 
   newNode->next=NULL;
   fread(&newNode->data,1,sizeof(struct book),fp);
//头插法建立链表  
   //没有结点 
   if(headNode==NULL){
   	  headNode=newNode; //新结点直接当成新头   	 
   } 
   //有结点 
   else{ 
   newNode->next=headNode;//新结点指向原表头
   headNode=newNode;//原表头指向新结点
		    
	//}   
	
	fclose(fp);//关闭文件 
	printf("Add Success");
	system("pause");//暂停 
    //system("cls");//清屏
	
	}
}
//参数：插入哪个链表，插入哪些数据 
void addNodeByTail()
{
    
	struct Node *newNode=(struct Node*)malloc(sizeof(struct Node));//调创建新结点 
	newNode->next=NULL;
	struct Node *tailNode=(struct Node*)malloc(sizeof(struct Node));  //创建尾结点用于记录最后一个结点 并初始化 
	tailNode->next=NULL;
	struct Node *headNode = newNode;
//录入新增图书各项信息 
	puts("Enter:");
	puts("Book Name");
	fflush(stdin);
	fgets(newNode->data.name, BUFFERSIZE, stdin);
	//scanf("%s",newNode->data.name);
	fflush(stdin); //To avoid the over-length string passed to Author
	printf("\tGet %s", newNode->data.name);
	puts("\nAuthor");
	fgets(newNode->data.author, BUFFERSIZE, stdin);
	//scanf("%s",newNode->data.author);
	fflush(stdin);
	printf("\nGet Author%s", newNode->data.author);
	puts("\nPublisher");
    scanf("%s",newNode->data.press);
	printf("\nGet Publisher:%s", newNode->data.press);
	puts("\nID code");
	scanf("%d",&newNode->data.num);

//先找到原链表最后一个结点 
	while(headNode->next!=NULL){
		headNode=headNode->next; //如果该结点下一个不是NULL 则下移一个结点 
	} 
	tailNode=headNode;//遍历后记录下最后一个结点 
    tailNode->next=newNode;//原尾结点指向新结点 
	newNode->next=NULL;//新结点下一个指向NULL 做表尾 
//保存到文件
	FILE *fp = fopen("D:\\testtxt\\a.txt","a");//打开文件 
	if(fp==NULL){
		printf("Not Such a file!\n");
	} 
	//fwrite(headNode->data.author,1,sizeof(headNode->data.author),fp);//读写数据
	fprintf(fp, "BookName: %s,\nAuthor: %s,\n Publisher: %s,\n ID:  %d\n\n", 
		headNode->data.name, headNode->data.author, headNode->data.press, headNode->data.num);
	fclose(fp);//关闭文件 
	puts("Saved"); 
	//system("pause");//暂停 
    system("cls");//清屏

} 
//num
struct Node* searchbynum()
{
	puts("Enter ID:");
	int stunum;
	scanf("%d",&stunum);
	struct Node*p=headNode;
	//遍历链表
	while(p->next != NULL){
		if(stunum==p->data.num) {
			return p;	//找到
		}
		p=p->next ; 
	} 
	return NULL;//没找到  返回值是Node型指针 
	system("pause");//暂停 
    system("cls");//清屏	
}

void deleteNode()
{
	puts("Enter the ID of the book you wanna delete");
	int stunum;
	scanf("%d",&stunum);
	struct Node*p1;
	//是头结点 
	if(headNode->data.num==stunum){
		p1=headNode;
		//删除头结点 头指向下一个 
		free(p1);
		headNode=headNode->next;	
	}
	//不是头结点 遍历查找 
	struct Node*p2=headNode;
	struct Node*p3=p2->next;
	while(p2->next!=NULL){
		if(p2->data.num==stunum){
			p3=p2->next;//被删结点 
			p2=p2->next->next;//连接被删结点下一个与下一个 
			free(p3);
			return;
		
		} 
		p2=p2->next;//移动到下一位 
	}
	system("pause");//暂停 
    system("cls");//清屏
	
	
}

void sortbyBubble()       
{

    struct Node* pre;
	struct Node*cur;
	struct Node*next;
	struct Node*end;
	struct Node*temp;//定义四个结构体类型指针 pre前一项 cur当前项 next后一项 end控制一趟中循环次数
	end->next=NULL;//相当于指向表尾 
	printf("Order From Smallest to Larges, according to ID：\n");
	while(headNode->next!=end->next)
	{
		//初始化三个指针 ; 判断是否到达结束位置 ; 三个指针集体后移
		for(pre=headNode,cur=pre->next,next=cur->next;  next!=end;  pre=pre->next,cur=cur->next,next=next->next){
			if(cur->data.num > next->data.num){ //从小到大
				pre->next=next;
				cur->next=next->next;
				next->next=cur;
				//此时next变前一项，cur变后一项  交换next cur的整个单元 
				temp=cur;
				cur=next; 
			    next=temp;
			}
		}
		end->next= cur->next;//next位置指向已经排好序的起始位置  故end=cur使结束条件移动到未排序的最后一个元素 
	}
	
	printlist();
	system("pause");//暂停 
    system("cls");//清屏
}


